﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Super.Entities;
using System.Web;

namespace Super.DomainService
{
    /// <summary> 全站Cookie服务提供者
    /// <remarks>bangq@2012.4/3改自bangke项目</remarks>
    /// </summary>
    public class CookieService
    {
        private const string UserCookieName = "Super_User";

        #region 操作Cookie根基 喉咙

        private static void SaveCookies(string cookieName, HttpCookie Cookies, bool isUpdate)
        {
            if (HttpContext.Current.Request.Cookies[cookieName] != null)
            {
                if (!isUpdate)
                    HttpContext.Current.Response.Cookies.Set(Cookies);   //覆盖    
                else
                {
                    //按需更新
                    HttpCookie haveCookies = HttpContext.Current.Request.Cookies[cookieName];
                    if (haveCookies != null && (Cookies.Values.Count > 0 && haveCookies.Values.Count > 0))
                    {
                        foreach (var item in Cookies.Values.AllKeys)
                        {
                            //if (HaveCookies.Values[item] != null) //如果已有的cookie组内有此子
                            //    HaveCookies.Values.Set(item, Cookies.Values[item]); //更新
                            //else
                            //    HaveCookies.Values.Add(item, Cookies.Values[item]); //增加子
                            haveCookies.Values[item] = Cookies.Values[item];

                        }
                        haveCookies.Domain = Cookies.Domain;
                        haveCookies.Expires = Cookies.Expires;
                        haveCookies.HttpOnly = true;

                        HttpContext.Current.Response.Cookies.Set(haveCookies);   //更新组
                    }


                }
            }
            else
            {
                HttpContext.Current.Response.Cookies.Add(Cookies);
            }

        }

        /// <summary>
        /// 保存Cookie 第二个values是List集合，添加为cookie组
        /// 示例：SaveCookies(cooke名, new List<string/>{"subName1=1","subName2=2"})
        /// </summary>
        /// <param name="cookieName"></param>
        /// <param name="values"></param>
        /// <param name="value"></param>
        /// <param name="Expires"></param>
        public static void SaveCookies(string cookieName, List<string> values = null, string value = "", double Expires = 0, bool isUpdate = false)
        {

            var cookies = new HttpCookie(cookieName);


            if (values != null && value == "")
            {
                foreach (var item in values)
                {
                    cookies.Values.Add(item.Split('=')[0], HttpUtility.UrlEncode(item.Split('=')[1], Encoding.UTF8));  //组写入item 默认转化url字符
                }
            }
            else
            {
                cookies.Value = HttpUtility.UrlEncode(value, Encoding.UTF8);
            }

            cookies.Domain = SuperService.Domain;
            cookies.Expires = DateTime.Now.AddHours(Expires);
            SaveCookies(cookieName, cookies, isUpdate); //保存
        }

        /// <summary>
        /// 保存单个普通cookie，默认设置24小时
        /// </summary>
        /// <param name="cookieName"></param>
        /// <param name="value"></param>
        public static void SaveCookies(string cookieName, string value, double expires = 24)
        {
            SaveCookies(cookieName, null, value, expires);//默认24小时
        }

        /// <summary>
        /// 保存cookie组，默认设置24小时
        /// </summary>
        /// <param name="cookieName"></param>
        /// <param name="values"> </param>
        /// <param name="expires"> </param>
        public static void SaveCookies(string cookieName, List<string> values, double expires = 24, bool isUpdate = false)
        {
            SaveCookies(cookieName, values, "", expires, isUpdate);
        }

        /// <summary>
        /// 更新cookie组，默认设置24小时
        /// </summary>
        /// <param name="cookieName"></param>
        /// <param name="values"> </param>
        /// <param name="Expires"> </param>
        public static void UpdateCookies(string cookieName, List<string> values, double Expires = 24)
        {
            SaveCookies(cookieName, values, "", Expires, true);
        }

        /// <summary>
        /// 获取当前指定cookie值,如果有子名称则读取子名称值,默认返回空
        /// </summary>
        /// <param name="cookieName"></param>
        /// <param name="subName"></param>
        /// <returns></returns>
        public static string GetCookies(string cookieName, string subName = "")
        {
            if (HttpContext.Current.Request.Cookies[cookieName] != null)
            {
                if (subName != "" && !string.IsNullOrEmpty(HttpContext.Current.Request.Cookies[cookieName].Values[subName]))
                    return HttpUtility.UrlDecode(HttpContext.Current.Request.Cookies[cookieName].Values[subName], Encoding.UTF8);
                else
                    return HttpUtility.UrlDecode(HttpContext.Current.Request.Cookies[cookieName].Value, Encoding.UTF8);
            }
            else
                return "";
        }

        /// <summary>
        /// 删除Cookie以Cookie名称
        /// </summary>
        /// <param name="CookieName"></param>
        public static void DeleteCookies(string CookieName)
        {
            HttpCookie cookie = HttpContext.Current.Request.Cookies[CookieName];

            if (cookie != null)
            {
                cookie.Expires = DateTime.Now.AddDays(-10); //删除cookie，设置已经过期
                cookie.Value = "";
                cookie.Domain = SuperService.Domain;
                HttpContext.Current.Response.SetCookie(cookie);
                HttpContext.Current.Response.Cookies.Set(cookie);
                HttpContext.Current.Request.Cookies.Remove(CookieName); //在删除一次
            }
            HttpContext.Current.Request.Cookies.Remove(CookieName); //在删除一次
        }

        #endregion

        #region 登录相关的Cookie操作，涉及了key验证 ，所以单纯分离出来

        /// <summary> 从Cookie中读取UID，没有即返回int最小值
        /// </summary>
        /// <returns></returns>
        public static int GetUID()
        {
            return (GetUserCookie() != null) ? GetUserCookie().Values["UID"].ToInt() : int.MinValue;
        }

        public static int GetUserID()
        {
            return (GetUserCookie() != null) ? GetUserCookie().Values["UserID"].ToInt() : int.MinValue;
        }
        /// <summary> 从Cookie中读取用户名
        /// </summary>
        /// <returns></returns>
        public static string GetUserName()
        {
            return (GetUserCookie() != null) ? HttpUtility.UrlDecode(GetUserCookie().Values["UserName"], Encoding.UTF8) : string.Empty;
        }

        public static int GetShopId()
        {
            return (GetUserCookie() != null) ? GetUserCookie().Values["ShopID"].ToInt() : int.MinValue;
        }

        /// <summary> 最近欺骗ID (用户有一次欺骗的机会)
        /// </summary>
        private static readonly HashSet<int> LastErrorUserHash = new HashSet<int>();
        private static DateTime _refLastErrorUserDate = DateTime.Now.AddHours(2);

        /// <summary> 读取用户Cookie，并且验证Key
        /// </summary>
        /// <returns></returns>
        private static HttpCookie GetUserCookie()
        {
            var usercookie = HttpContext.Current.Request.Cookies[UserCookieName];

            if (usercookie != null)
            {
                if (usercookie.Values["Key"] == Common.Security.MD5.FormatCookieByUser(usercookie.Values["UserName"] + usercookie.Values["UserID"] + usercookie.Values["UID"]))
                {
                    return usercookie;
                }

                //每人有一次欺骗机会.(其实是自然超时- -#)
                var uid = usercookie.Values["UserID"].ToInt();

                //小锁一下.
                lock (LastErrorUserHash)
                {
                    //2小时清空一次记录.
                    if (_refLastErrorUserDate < DateTime.Now)
                    {
                        _refLastErrorUserDate = _refLastErrorUserDate.AddHours(2);
                        LastErrorUserHash.Clear();
                    }

                    if (LastErrorUserHash.Contains(uid))
                    {
                       // LogService.AddLog(LogOperation.Safe, "Cookie用户名为" + HttpUtility.UrlDecode(usercookie.Values["UserName"], Encoding.UTF8) + ",ID为" + uid + "的用户涉嫌Cookie欺骗!", uid);
                    }
                    else
                    {
                        LastErrorUserHash.Add(uid);
                    }
                }

                DeleteUserCookies();
            }
            return null;

            // return (usercookie != null && usercookie.Values["Key"] == BK.Common.Security.MD5.FormatCookieByUser(usercookie.Values["UserName"] + usercookie.Values["UserID"] + usercookie.Values["UID"])) ? usercookie : null;
        }


        /// <summary>
        /// 保存用户登录Cookie
        /// </summary>
        /// <param name="user">用户实体</param>
        /// <param name="expires">Cookie过期小时数</param>
        /// <param name="shopId"></param>
        public static void SaveUserCookies(User user,double expires = 24,int shopId=0)
        {
            if (user == null) return;

            var cookie = new List<string>
                             {
                                 "UserID=" + user.ID,
                                 "UID=" + user.UID,
                                 "UserName=" + user.Name,
                                 "ShopID="+shopId,
                                 "Key=" + Common.Security.MD5.FormatCookieByUser(user.Name + user.ID + user.UID)
                                 //加密key的参数及顺序要与解密对应
                             };

            SaveCookies(UserCookieName, cookie, expires);
        }

        /// <summary>
        /// 删除当前用户登录Cookie
        /// </summary>
        public static void DeleteUserCookies()
        {
            DeleteCookies(UserCookieName);
        }


        #endregion
    }
}